package com.cyw.common.utils.http;

import com.cyw.common.constants.CommonConstant;
import com.cyw.common.utils.BaseUtils;
import com.cyw.common.utils.LogUtils;
import com.cyw.common.utils.web.HttpRequestBodyCacheFilter;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.http.HttpServletRequest;
import java.nio.charset.Charset;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;

/**
 * http工具
 *
 * @author sxw
 * @date 2018-11-23
 * @see HttpClientUtils
 */
public class HttpUtils {

    private static final Logger LOGGER = LoggerFactory.getLogger(HttpUtils.class);
    private static final int DEFAULT_MAX_OUTPUT_PARAM_LENGTH = 1000;


    /**
     * 获取请求头,以map形式返回
     * @param request
     * @return
     */
    public static Map<String, String> getHeaders(HttpServletRequest request) {
        Map<String, String> headers = new HashMap<>();
        Enumeration<String> headerNames = request.getHeaderNames();
        while (headerNames.hasMoreElements()) {
            String headerName = headerNames.nextElement();
            Enumeration<String> requestHeaders = request.getHeaders(headerName);
            StringBuilder tmp = new StringBuilder();
            while (requestHeaders.hasMoreElements()) {
                tmp.append(requestHeaders.nextElement()).append("#");
            }

            int indexOf = tmp.lastIndexOf("#");
            if (indexOf >= 0) {
                tmp.deleteCharAt(indexOf);
            }
            headers.put(headerName, tmp.toString());
        }

        LOGGER.trace("headers(map):{}", headers);
        return headers;
    }

    /**
     * 获取请求参数,以map形式返回
     * @param request
     * @return
     */
    public static Map<String, String> getParams(HttpServletRequest request) {
        return getParams(request, false);
    }

    /**
     * 获取请求参数,以map形式返回，超过默认长度就截断
     * @param request
     * @param truncateLong
     * @return
     */
    public static Map<String, String> getParams(HttpServletRequest request, boolean truncateLong) {
        return getParams(request, truncateLong, DEFAULT_MAX_OUTPUT_PARAM_LENGTH);
    }

    /**
     * 获取请求参数,以map形式返回
     * 目前只支持x-www-form-urlencoded或者查询字符串中的参数
     * 不支持form-data中的参数, 除非request对象重写了获取参数的方法，比如:
     * @see org.springframework.web.multipart.MultipartHttpServletRequest
     * 获取实体中的参数参考：
     * @see #getBodyParams(HttpServletRequest)
     *
     * @param request
     * @param truncateLong 参数值超过一定长度会被截断
     * @param truncateLength truncateLong为false时会忽略该值
     * @return
     */
    public static Map<String, String> getParams(HttpServletRequest request, boolean truncateLong, int truncateLength) {
        Map<String, String> params = new HashMap<>();
        Enumeration<String> parameterNames = request.getParameterNames();
        while (parameterNames.hasMoreElements()) {
            String paramName = parameterNames.nextElement();
            String[] paramValues = request.getParameterValues(paramName);
            String tmp = paramValues.length > 0 ? paramValues[0] : "";
            StringBuilder sb = new StringBuilder(tmp);
            for (int i = 1; i < paramValues.length; i++) {
                sb.append(",").append(paramValues[i]);
            }

            String value = sb.toString();
            boolean tooLong = value != null && value.length() > truncateLength;
            if (truncateLong && tooLong) {
                LOGGER.debug("截断前字符串：{}", value);
                value = value.substring(0, truncateLength);
            }
            params.put(paramName, value);
        }
        return params;
    }

    /**
     * 获取请求客户端的实际IP
     * @param request
     * @return
     */
    public static String getRequestIp(HttpServletRequest request) {
        String ip = request.getHeader("X-Forwarded-For");
        if (StringUtils.isBlank(ip) || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (StringUtils.isBlank(ip) || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (StringUtils.isBlank(ip) || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_CLIENT_IP");
        }
        if (StringUtils.isBlank(ip) || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_X_FORWARDED_FOR");
        }
        if (StringUtils.isBlank(ip) || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        return ip;
    }

    /**
     * 获取请求实体参数
     * 使用这个方法会读取流，一般后续需要使用该流中的数据，所以需要保证请求对象可以重复读取
     * 只会打印请求类型为json的实体
     * @param request
     * @return
     * @see HttpRequestBodyCacheFilter
     * @see #getParams(HttpServletRequest)
     * @see CommonConstant#CONTENT_TYPE_JSON
     */
    public static String getBodyParams(HttpServletRequest request) {
        String body = null;
        try {
            if (request instanceof HttpRequestBodyCacheFilter.CachedHttpRequest) {
                body = new String(((HttpRequestBodyCacheFilter.CachedHttpRequest)request).getBytes(), Charset.forName(CommonConstant.ENCODING));
                if (BaseUtils.isNotBlank(body)) {
                    body = body.trim();
                }
            }
        } catch (Exception e) {
            LogUtils.printWarn(e, "未知异常" + e.getMessage());
        }
        return body;
    }
}
